﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlueLotus7.ArchiveSystem.Interfaces;
using BlueLotus7.ArchiveSystem.Common;
using BlueLotus7.Eden.Service.BusinessLayer;

namespace BlueLotus7.Eden.Service
{
    public class ArchiveStatusService : ArchiveSystemCommonService, IArchiveStatusService
    {
        public ArchiveStatusService()
        {
            dataAdapter = new StatusDataAdapter();
        }

        public ArchiveStatusService(bool throwException)
            : this()
        {
            this.throwException = throwException;
        }

        public bool ReportStatus(Guid monitorClientKey, Guid domainScopeKey, Guid domainScopeUserKey, int status)
        {
            bool needSyncTasks = false;
            try
            {
                ((StatusDataAdapter)dataAdapter).ReportStatus(domainScopeKey, domainScopeUserKey, status);

                if (!Global.StatusClientSyncList.ContainsKey(monitorClientKey))
                {
                    needSyncTasks = true;
                }
                else
                {
                    SettingSyncItem item = Global.StatusClientSyncList[monitorClientKey];
                    needSyncTasks = (item.LastSyncStamp == null || (item.LastUpdateStamp != null && item.LastUpdateStamp.Value > item.LastSyncStamp));
                }
            }
            catch (Exception ex)
            {
                var data = new
                {
                    monitorClientKey = monitorClientKey,
                    domainScopeKey = domainScopeKey,
                    domainScopeUserKey = domainScopeUserKey,
                    status = status
                };
                Exception exception = new Exception(LogMessageHelper.GetFailedOperationMessage("report", "status"), ex);
                Global.Logger.LogException(exception, data);
                if (this.throwException)
                {
                    throw exception;
                }
            }

            return needSyncTasks;
        }

        public List<TargetStatus> QueryStatus(Guid? domainScopeKey, Guid? domainScopeUserKey, DateTime? startStamp, DateTime? endStamp)
        {
            List<TargetStatus> result = new List<TargetStatus>();

            try
            {
                DateTime now = DateTime.Now;
                DateTime temp = startStamp == null ? now : startStamp.Value;
                startStamp = new DateTime(temp.Year, temp.Month, temp.Day, 0, 0, 0);

                temp = (endStamp == null || endStamp.Value < startStamp.Value) ? startStamp.Value : endStamp.Value;
                endStamp = new DateTime(temp.Year, temp.Month, temp.Day, 0, 0, 0);
                endStamp = endStamp.Value.AddDays(1).AddSeconds(-1);

                result = ((StatusDataAdapter)dataAdapter).QueryStatus(domainScopeKey, domainScopeUserKey, startStamp.Value, endStamp.Value);
            }
            catch (Exception ex)
            {
                var data = new
                {
                    domainScopeKey = domainScopeKey,
                    domainScopeUserKey = domainScopeUserKey,
                    startStamp = startStamp,
                    endStamp = endStamp
                };
                Exception exception = new Exception(LogMessageHelper.GetFailedOperationMessage("query", "status"), ex);
                Global.Logger.LogException(exception, data);
                if (this.throwException)
                {
                    throw exception;
                }
            }

            return result;
        }

        public TargetStatus RetrieveLatestStatus(Guid domainScopeKey, Guid domainScopeUserKey)
        {
            TargetStatus result = null;

            try
            {
                result = ((StatusDataAdapter)dataAdapter).GetLatestStatus(domainScopeKey, domainScopeUserKey);
            }
            catch (Exception ex)
            {
                var data = new
                {
                    domainScopeKey = domainScopeKey,
                    domainScopeUserKey = domainScopeUserKey
                };
                Exception exception = new Exception(LogMessageHelper.GetFailedOperationMessage("retrieve", "latest status"), ex);
                Global.Logger.LogException(exception, data);
                if (this.throwException)
                {
                    throw exception;
                }
            }

            return result;
        }

        public List<DomainScopeUserFullInfo> GetDomainScopeUsersWithStatus(Guid? domainScopeKey)
        {
            List<DomainScopeUserFullInfo> result = new List<DomainScopeUserFullInfo>();
            try
            {
                result = ((StatusDataAdapter)dataAdapter).GetDomainScopeUsersWithStatus(domainScopeKey);
            }
            catch (Exception ex)
            {
                var data = new
                {
                    domainScopeKey = domainScopeKey,
                };
                Exception exception = new Exception(LogMessageHelper.GetFailedOperationMessage("get", "scope users with status"), ex);
                Global.Logger.LogException(exception, data);
                if (this.throwException)
                {
                    throw exception;
                }
            }

            return result;
        }

        public List<DomainScopeUser> RetrieveScopeUsersToMonitor(Guid domainScopeKey, Guid monitorClientKey)
        {
            List<DomainScopeUser> result = new List<DomainScopeUser>();
            try
            {
                if (!Global.StatusClientSyncList.ContainsKey(monitorClientKey))
                {
                    Global.StatusClientSyncList.Add(monitorClientKey, new SettingSyncItem
                    {
                        ClientKey = monitorClientKey,
                        DomainScopeKey = domainScopeKey
                    });
                }
                Global.StatusClientSyncList[monitorClientKey].LastSyncStamp = DateTime.Now;

                result = ((StatusDataAdapter)dataAdapter).GetDomainScopeUsersForMonitor(domainScopeKey);
            }
            catch (Exception ex)
            {
                var data = new
               {
                   monitorClientKey = monitorClientKey,
                   domainScopeKey = domainScopeKey,
               };
                Exception exception = new Exception(LogMessageHelper.GetFailedOperationMessage("retrieve", "scope users to monitor"), ex);
                Global.Logger.LogException(exception, data);
                if (this.throwException)
                {
                    throw exception;
                }
            }

            return result;
        }

        /// <summary>
        /// Merge status
        /// </summary>
        /// <param name="domainScopeUserKey"></param>
        /// <param name="status"></param>
        /// <param name="startGuid"></param>
        /// <param name="endGuid"></param>
        public void MergeStatus(Guid domainScopeUserKey, int status, Guid startGuid, Guid endGuid)
        {
            try
            {
                ((StatusDataAdapter)dataAdapter).MergeStatus(domainScopeUserKey, status, startGuid, endGuid);
            }
            catch (Exception ex)
            {
                var data = new
                {
                    domainScopeUserKey = domainScopeUserKey,
                    status = status,
                    startGuid = startGuid,
                    endGuid = endGuid
                };
                Exception exception = new Exception(LogMessageHelper.GetFailedOperationMessage("merge", "status"), ex);
                Global.Logger.LogException(exception, data);
                if (this.throwException)
                {
                    throw exception;
                }
            }
        }
    }
}
